/*************************************************
* Title：TinyToolKit
* Author：Opportunity 
* Describe：
* CreateTime：2021-06-29 09:53:11
* Version：1.0
* Modify Recorder：
*************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using UnityEngine;
using Random = System.Random;

namespace TinyToolKit
{
    public static partial class TinyUtility
    {
        public static class Network
        {
            //查询本地可用的IP地址
            public static List<string> ScanLocalAddress()
            {
                List<string> addressList = new List<string>();
                //安卓端
                if (Application.platform == RuntimePlatform.Android)
                {
                    //获取设备的主机名
                    var host = Dns.GetHostEntry(Dns.GetHostName());
                    foreach (var address in host.AddressList)
                    {
                        //判断是不是IPV4
                        if (address.AddressFamily == AddressFamily.InterNetwork)
                        {
                            string addr = address.ToString();
                            if (!addressList.Contains(addr))
                                addressList.Add(addr);
                        }
                    }
                }

                if (addressList.Count > 0) return addressList;
                //NetworkInterface，此类封装本地计算机上的网络接口（也称为适配器）的数据,可以通过它检测本机配置了多少网卡，哪些网络连接可用，获得网卡的MAC地址和速度等。
                //GetAllNetworkInterfaces，返回所有的网络适配器
                NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
                if (adapters.Length < 1)
                {
                    TLogTool.Error("未发现网络接口！");
                    return addressList;
                }

                foreach (var item in adapters)
                {
                    //Loopback = 127.0.0.1，该网络接口是回环适配器。 此类接口通常用于测试；不会通过线路发送任何流量
                    if (item.NetworkInterfaceType == NetworkInterfaceType.Loopback) continue;

                    //OperationalStatus，指定网络接口的操作状态
                    //OperationalStatus.Up，网络接口已运行，可以传输数据包
                    if (item.OperationalStatus != OperationalStatus.Up) continue;

                    //GetIPProperties，返回描述此网络接口的配置的对象
                    //UnicastAddresses，获取分配给此接口的单播地址
                    foreach (var ipAddr in item.GetIPProperties().UnicastAddresses)
                    {
                        if (ipAddr.Address.AddressFamily == AddressFamily.InterNetwork)
                        {
                            string addr = ipAddr.Address.ToString();
                            if (!addressList.Contains(addr))
                                addressList.Add(addr);
                        }
                    }
                }

                return addressList;
            }
            
            //随机获取本地可用的Port端口号
            public static int GetRandomPort()
            {
                List<int> HasUsedPort = PortIsUsed();
                int port = 0;
                bool IsRandomOk = true;
                Random random = new Random((int) DateTime.Now.Ticks);
                while (IsRandomOk)
                {
                    port = random.Next(1024, 65535);
                    IsRandomOk = HasUsedPort.Contains(port);
                }

                return port;
            }

            // 获取操作系统已用的端口号   
            private static List<int> PortIsUsed()
            {
                //获取本地计算机的网络连接和通信统计数据的信息           
                IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();

                //返回本地计算机上的所有Tcp监听程序            
                IPEndPoint[] ipsTCP = ipGlobalProperties.GetActiveTcpListeners();

                //返回本地计算机上的所有UDP监听程序            
                IPEndPoint[] ipsUDP = ipGlobalProperties.GetActiveUdpListeners();

                //返回本地计算机上的Internet协议版本4(IPV4 传输控制协议(TCP)连接的信息。            
                TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();

                List<int> allPorts = new List<int>();
                foreach (IPEndPoint ep in ipsTCP)
                {
                    allPorts.Add(ep.Port);
                }

                foreach (IPEndPoint ep in ipsUDP)
                {
                    allPorts.Add(ep.Port);
                }

                foreach (TcpConnectionInformation conn in tcpConnInfoArray)
                {
                    allPorts.Add(conn.LocalEndPoint.Port);
                }

                return allPorts;
            }
        }
    }
}